<?php

/**
 * Power By Tmac PHP MVC framework
 * $Author: zwt007 $  <zwttmac@qq.com>
 * $Id: Tmac.class.php 31 2011-07-11 15:25:51Z zwt007 $
 * http://www.t-mac.org； 
 */
class Tmac
{

    /**
     * Model的instance数组
     *
     * @var array
     */
    protected static $model = array();

    /**
     * core
     */
    public function __construct()
    {

        global $TmacConfig;
        //设置编码
        header("Content-type: text/html;charset={$TmacConfig['Common']['charset']}");

        //设置时区
        @date_default_timezone_set($TmacConfig['Common']['timezone']);

        //生成htaccess文件
        $htaccess = WEB_ROOT . '.htaccess';
        if ($TmacConfig['Common']['urlrewrite']) {
            if (is_file($htaccess)) {
                if (filesize($htaccess) > 132) {
                    //如果程序无法删除就需要手动删除
                    unlink($htaccess);
                    file_put_contents($htaccess, "RewriteEngine on\r\nRewriteBase " . ROOT . "\r\nRewriteCond %{SCRIPT_FILENAME} !-f\r\nRewriteCond %{SCRIPT_FILENAME} !-d\r\nRewriteRule ^.*$ index.php", LOCK_EX);
                }
            }
        }

        //不进行魔术过滤 php5.3废除了 set_magic_quotes_runtime(0);
        ini_set("magic_quotes_runtime", 0);

        //开启页面压缩
        if ($TmacConfig['Common']['gzip']) {
            function_exists('ob_gzhandler') ? ob_start('ob_gzhandler') : ob_start();
        } else {
            ob_start();
        }

        //页面报错
        $TmacConfig['Common']['errorreport'] ? error_reporting(E_ALL) : error_reporting(0);

        //控制异常
        set_exception_handler(array($this, 'exception'));

        session_start();

        //Router
        new Controller();
    }

    /**
     * 载入Model
     *
     * @param string $model Model名 类名必须与文件名一致 "/"作为目录分隔符
     * @param string $app_name 项目名（如果需要跨项目调用）
     * @param string $ext   后缀名
     * @return object
     * @access public
     * @static
     */
    public final static function model($model, $app_name = APP_NAME, $ext = '.class.php')
    {
        //判断是否已经创建过此Model
        if (!array_key_exists($model, self::$model)) {
            //存在
            $file = TMAC_BASE_PATH . $app_name . DIRECTORY_SEPARATOR . APPLICATION . DIRECTORY_SEPARATOR . 'Model' . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $model) . $ext;
            if (is_file($file)) {
                include_once($file);
                $model = str_replace('/', '', ($tmp = strrchr($model, '/')) === false ? $model : $tmp);
                $m = new $model();
                //执行_init方法
                in_array('_init', get_class_methods($model)) && $m->_init();
                //储存到model数组中 下次调用不再new
                self::$model[$model] = $m;
                return $m;
            } else {
                throw new TmacException('找不到Model文件:' . $file);
            }
        } else {
            //不存在
            in_array('_init', get_class_methods(self::$model[$model])) && self::$model[$model]->_init();
            return self::$model[$model];
        }
    }

    /**
     * 载入插件
     *
     * @param string $plugin   插件名 插件类名必须与文件名一致 "."作为目录分隔符
     * @param array $param     插件参数
     * @param string $ext      插件后缀名
     * @return object
     * @access public
     * @static
     */
    public final static function plugin($plugin, $param = array(), $ext = '.class.php')
    {
        $file_tmac = TMAC_PATH . 'Plugin' . DIRECTORY_SEPARATOR . str_replace('.', DIRECTORY_SEPARATOR, $plugin) . $ext;
        $file_app = APPLICATION_ROOT . 'Plugin' . DIRECTORY_SEPARATOR . str_replace('.', DIRECTORY_SEPARATOR, $plugin) . $ext;
        if (is_file($file_tmac)) {
            $file = $file_tmac;
        } elseif (is_file($file_app)) {
            $file = $file_app;
        } else {
            throw new TmacException('找不到Tmac核心包中的Plugin文件:' . $file_tmac . ',也找不到' . APP_NAME . '核心包中的Plugin文件:' . $file_app);
        }
        include_once($file);
        $plugin = str_replace('.', '', ($tmp = strrchr($plugin, '.')) === false ? $plugin : $tmp);
        return empty($param) ? new $plugin() : new $plugin($param);
    }

    /**
     * 输出模板
     * 
     * @param string $view 模板路径以及文件名 可以用.作为目录分割
     */
    public final static function view($view = null)
    {
        global $TmacConfig;
        $options = array(
            'template_dir' => APPLICATION_ROOT . $TmacConfig['Template']['template'], //设置系统模板文件的存放目录
            'cache_dir' => VAR_ROOT . $TmacConfig['Template']['cache_dir'], //指定缓存文件存放目录
            'auto_update' => $TmacConfig['Template']['auto_update'], //当模板文件有改动时重新生成缓存 [关闭该项会快一些]
            'cache_lifetime' => $TmacConfig['Template']['cache_lifetime'], //缓存生命周期(分钟)，为 0 表示永久 [设置为 0 会快一些]
            'suffix' => $TmacConfig['Template']['suffix'], //模板后缀
            'cache_open' => $TmacConfig['Template']['cache_open']           //是否开启缓存，程序调试时使用
        );
        $tpl = Template::getInstance();
        $tpl->setOptions($options); //设置模板参数
        //如果模板路径，文件名为空的话就尝试把TMAC_CONTROLLER_FILE当作模板路径，文件名
        if ($view == $TmacConfig['Template']['template_admin_dir'] . DIRECTORY_SEPARATOR || $view == $TmacConfig['Template']['template_dir'] . DIRECTORY_SEPARATOR) {
            $view_new = strtolower($_GET['TMAC_CONTROLLER_FILE']);  //都转成小写的
            //如果是前台的模板就不用前缀（模板目录名）
            if ($view == $TmacConfig['Template']['template_dir'] . DIRECTORY_SEPARATOR) {
                $view = $view . $view_new;  //前面加上模板目录名
            } else {
                $view = $view_new;
            }
        }
        $tpl->show($view);
    }

    /**
     * 获取某个文件的路径
     *
     * @param string $file 文件路径
     * @return void
     * @access public
     * @static
     */
    public final static function file($file)
    {
        $file = str_replace(array('\\', '//', '\\\\'), '/', $file);
        return TMAC_BASE_PATH . $file;
    }

    /**
     * 载入Config
     *
     * @param string $model Model名 类名必须与文件名一致 "."作为目录分隔符
     * @param string $app_name   项目名
     * @param string $ext   后缀名
     * @return object
     * @access public
     * @static
     */
    public final static function config($model, $app_name = APP_NAME, $ext = '.php')
    {
        // Extract the main group from the key
        $group_array = explode('.', $model, 2);
        $group = $group_array[0];
        //存在
        $file = TMAC_BASE_PATH . $app_name . DIRECTORY_SEPARATOR . APPLICATION . DIRECTORY_SEPARATOR . 'Config' . DIRECTORY_SEPARATOR . str_replace('.', DIRECTORY_SEPARATOR, $group) . $ext;
        if (is_file($file)) {
            include($file);
            // Get the line from cache
            $line = self::key_string($config, $model);
            
            if ($line === NULL) {                
                //self::log('error', 'Missing i18n entry ' . $key . ' for language ' . $locale);
                throw new TmacException('找不到Config文件:' . $file);
                // Return the key string as fallback
                return $key;
            }

            if (is_string($line) AND func_num_args() > 1) {
                $args = array_slice(func_get_args(), 1);

                // Add the arguments into the line
                $line = vsprintf($line, is_array($args[0]) ? $args[0] : $args);
            }
            return $line;
        } else {
            throw new TmacException('找不到Config文件:' . $file);
        }
    }

    /**
     * Returns the value of a key, defined by a 'dot-noted' string, from an array.
     *
     * @param   array   array to search
     * @param   string  dot-noted string: foo.bar.baz
     * @return  string  if the key is found
     * @return  void    if the key is not found
     */
    public final static function key_string($array, $keys)
    {
        if (empty($array))
            return NULL;

        // Prepare for loop
        $keys = explode('.', $keys);
        $keys = array_splice($keys, 1);//去除数组中第一个也就是名
        do {
            // Get the next key
            $key = array_shift($keys);

            if (isset($array[$key])) {
                if (is_array($array[$key]) AND !empty($keys)) {
                    // Dig down to prepare the next loop
                    $array = $array[$key];
                } else {                    
                    // Requested key was found
                    return $array[$key];
                }
            } else {                
                // Requested key is not set
                break;
            }
        } while (!empty($keys));

        return NULL;
    }

    /**
     * 获取缓存实例
     *
     * @return object
     * @access public
     * @static
     */
    public final static function getCache()
    {
        return CacheDriver::getInstance();
    }

    /**
     * 获取数据库连接实例
     *
     * @return objeact
     * @access public
     * @static
     */
    public final static function getDB($name)
    {
        return DatabaseDriver::getInstance($name);
    }

    /**
     * 获取模板引擎实例
     *
     * @return object
     * @access public
     * @static
     */
    public final static function getTemplate()
    {
        return Template::getInstance();
    }

    /**
     * 控制异常的回调函数
     * 回调函数必须为public
     * 
     * @param object $e
     * @access public
     */
    public final function exception($e)
    {
        $e->getError();
    }

}